package net.atomarrow.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * 文件操作工具类
 * 
 * @author Michael
 * 
 */
public class FileUtil {

    public static File createFolder(String folder) {
        return autoCreateFolder(folder);
    }

    public static File[] getFiles(String folder) {
        File fd = new File(folder);
        if (!fd.exists()) {
            return null;
        } else {
            return fd.listFiles();
        }
    }

    /**
     * 复制文件|文件夹
     * 
     * @param srcFolder
     *            源文件|文件夹
     * @param destFolder
     *            目标文件|文件夹
     * @return
     */
    public static boolean copyFile(String srcFolder, String destFolder) {
        File src = new File(srcFolder);
        if (!src.exists()) {
            System.out.println("复制失败：复制源文件不存在");
            return false;
        }
        File dest = new File(destFolder);
        if (!dest.exists()) {
            if (src.isDirectory()) {
                dest.mkdir();
            }
        }
        return copyFile(src, dest);
    }

    /**
     * 复制文件夹
     * 
     * @param srcFolder
     *            源文件夹
     * @param destFolder
     *            目标文件夹
     * @return
     */
    private static boolean copyFile(File srcFolder, File destFolder) {
        try {
            if (!srcFolder.isDirectory()) {
                InputStream is = null;
                OutputStream os = null;
                try {
                    is = new FileInputStream(srcFolder);
                    os = new FileOutputStream(destFolder);
                    writeFile(is, os);
                } finally {
                    is.close();
                    os.close();
                }
                return true;
            }
            File[] files = srcFolder.listFiles();

            for (File file : files) {
                if (file.isDirectory()) {
                    File dest = new File(destFolder + "/" + file.getName());
                    if (!dest.exists()) {
                        dest.mkdir();
                    }
                    copyFile(file, dest);
                } else {
                    InputStream is = null;
                    OutputStream os = null;
                    try {
                        is = new FileInputStream(file);
                        os = new FileOutputStream(new File(destFolder + "/"
                                + file.getName()));
                        writeFile(is, os);
                    } finally {
                        is.close();
                        os.close();
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;

    }

    /**
     * 删除文件、文件夹
     * 
     * @param path
     *            需要删除的文件|文件夹
     */
    public static boolean delFile(String path) {
        try {
            delFile(new File(path));
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 开启一个线程进行删除文件、文件夹
     * 
     * @param path
     *            需要删除的文件|文件夹
     */
    public static void delFileWithThread(final String path) {
        new Thread(new Runnable() {
            public void run() {
                delFile(path);
            }
        }).start();
    }

    /**
     * 删除文件、文件夹
     * 
     * @param path
     *            需要删除的文件|文件夹
     */
    private static void delFile(File path) {
        if (path.isDirectory()) {
            File[] child = path.listFiles();
            if (child != null && child.length != 0) {
                for (int i = 0; i < child.length; i++) {
                    delFile(child[i]);
                    child[i].delete();
                }
            }
            path.delete();
        } else {
            path.delete();
        }
    }

    /**
     * 将输入流信息写入到输出流中
     * 
     * @param is
     * @param os
     * @throws IOException
     */
    public static void writeFile(InputStream is, OutputStream os)
            throws IOException {
        byte[] datas = new byte[4 * 1024];
        try {
            int l;
            while ((l = is.read(datas)) != -1) {
                os.write(datas, 0, l);
                os.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将输入流信息写入到输出流中
     * 
     * @param is
     * @param os
     * @throws IOException
     */
    public static void writeFile(InputStream is, String path)
            throws IOException {
        writeFile(is, new File(path));
    }

    /**
     * 将输入流信息写入到输出流中
     * 
     * @param is
     * @param os
     * @throws IOException
     */
    public static void writeFile(InputStream is, File file) throws IOException {
        writeFile(is, new FileOutputStream(file));
    }

    private static File autoCreateFolder(String path) {
        File f = new File(path);
        if (!f.exists()) {
            f.mkdirs();
        }
        return f;
    }

    /**
     * 储存一个对象
     * 
     * @param path
     *            路径
     * @param obj
     *            对象
     * @param autoCreate
     *            是否自动创建文件夹
     * @return boolean
     * @throws IOException
     */
    public static boolean saveObject(String path, Object obj, boolean autoCreate)
            throws IOException {
        File file = new File(path);
        path = file.getAbsolutePath();
        if (autoCreate) {
            autoCreateFolder(path);
        }

        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = new FileOutputStream(file);

            oos = new ObjectOutputStream(fos);

            oos.writeObject(obj);
            oos.flush();
            fos.flush();
        } finally {
            oos.close();
            fos.close();

        }

        return true;
    }

    /**
     * 读取一个对象
     * 
     * @param <T>
     * @param path
     * @param clazz
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static <T> T readObject(String path, Class<T> clazz)
            throws IOException, ClassNotFoundException {
        File file = new File(path);

        FileInputStream fis = null;
        ObjectInputStream ois = null;

        try {
            fis = new FileInputStream(file);
            ois = new ObjectInputStream(fis);

            T t = (T) ois.readObject();

            return t;

        } finally {
            if (fis != null) {
                fis.close();

            }
            if (ois != null) {
                ois.close();
            }
        }
    }

    /**
     * 储存集合中的数据
     * 
     * @param path
     *            路径
     * @param datas
     *            对象集合
     * @param autoCreate
     *            是否自动创建文件夹
     * @return boolean
     */
    public static boolean saveList(String path, List<?> datas,
            boolean autoCreate) {

        File file = new File(path);

        path = file.getAbsolutePath();
        if (autoCreate) {
            autoCreateFolder(path);
        }

        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = new FileOutputStream(file);

            oos = new ObjectOutputStream(fos);

            for (int i = 0; i < datas.size(); i++) {
                oos.writeObject(datas.get(i));
            }
            oos.writeObject(null);
            oos.flush();
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                oos.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        return true;
    }

    /**
     * 读取硬盘中的集合数据
     * 
     * @param <T>
     * @param path
     *            路径
     * @param clazz
     *            数据
     * @return List
     */

    public static <T> List<T> readList(String path, Class<T> clazz) {
        List<T> ts = new ArrayList<T>();
        File file = new File(path);

        FileInputStream fis = null;
        ObjectInputStream ois = null;

        try {
            fis = new FileInputStream(file);
            ois = new ObjectInputStream(fis);

            while (true) {
                T t = (T) ois.readObject();
                if (t == null) {
                    break;
                } else {
                    ts.add(t);
                }
            }

            return ts;

        } catch (FileNotFoundException e) {

            e.printStackTrace();
            return null;
        } catch (IOException e) {

            e.printStackTrace();
            return null;
        } catch (ClassNotFoundException e) {

            e.printStackTrace();
            return null;
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {

                    e.printStackTrace();
                }

            }
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {

                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 储存文件 
     * @param savePlace 地址
     * @param fileName 文件名
     * @param context 内容
     */
    public static void saveFile(String savePlace, String fileName,
            String context) {

        mkDir(savePlace);
        try {
            if (fileName != null) {
                String path = null;
                if(!savePlace.endsWith("/")||!savePlace.endsWith("\\\\")){
                    path=savePlace +File.separatorChar+fileName;
                }else{
                    path=savePlace+fileName;
                }
                File file = new File(path);
                if (!file.exists()) {
                    file.createNewFile();
                }
                FileOutputStream out = new FileOutputStream(file, false);
                if (context != null) {
                    out.write(context.getBytes(StandardCharsets.UTF_8));
                }
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void mkDir(String savePlace) {
        if (savePlace != null) {
            File dir = new File(savePlace);
            if (!dir.exists()) {
                dir.mkdirs();
            }
        }
    }

    /**
     * 检查上传的文件后缀名是否为指定后缀
     * 
     * @param suffix
     * @return
     */
    public static boolean checkSuffix(String fileName,String suffix) {
        return getFileSuffix(fileName).equals(suffix);
    }
    /**
     * 检查上传的文件后缀名是否为图像格式后缀
     * 
     * @param fileName
     * @return
     */
    public static boolean checkImageSuffix(String fileName) {
    	return checkSuffix(fileName,"jpg","jpeg","JPG","png","PNG");
    }
    /**
     * 检查上传的文件后缀名是否为Excel后缀
     * 
     * @param fileName
     * @return
     */
    public static boolean checkExcelSuffix(String fileName) {
    	return checkSuffix(fileName,"xls","xlsx");
    }
    /**
     * 检查上传的文件后缀名是否为PDF后缀
     * 
     * @param fileName
     * @return
     */
    public static boolean checkPdfSuffix(String fileName) {
    	return checkSuffix(fileName,"pdf");
    }
    /**
     * 检查上传的文件后缀名是否为office办公文件后缀
     * 
     * @param fileName
     * @return
     */
    public static boolean checkOfficeSuffix(String fileName) {
    	return checkSuffix(fileName,"doc","docx","ppt","pptx","xls","xlsx");
    }
    /**
     * 检查上传的文件后缀名是否为不可上传文件后缀
     * 
     * @param fileName
     * @return
     */
    public static boolean checkDangerSuffix(String fileName) {
        return checkSuffix(fileName,"exe","o","jsp","js","asp","bat");
    }
    /**
     * 检查上传的文件后缀名是否为指定后缀
     * 
     * @param fileName
     * @param suffix
     * @return
     */
    public static boolean checkSuffix(String fileName,String... suffixArray) {
        if(suffixArray==null||suffixArray.length==0){return false;}
        String fileSuffix=getFileSuffix(fileName);
        if(StringUtil.isBlank(fileSuffix)){return false;}
        return ArrayUtil.contains(suffixArray, fileSuffix);
    }
    /**
     * 获取文件后缀名
     * 
     * @param fileName
     * @return
     */
    public static String getFileSuffix(String fileName) {
        if(StringUtil.isBlank(fileName)){
            return "";
        }
        String filesuffix = null;
        StringTokenizer fx = new StringTokenizer(fileName, ".");
        while (fx.hasMoreTokens()) {
            filesuffix = fx.nextToken();
        }
        return filesuffix.toLowerCase();
    }
}
